#include "CustomWindow.h"
#include <QPainter>
#include <QMouseEvent>

CustomWindow::CustomWindow(QWidget *parent) :
	QWidget(parent),
	_resizable(true),
	_headerHeight(32),
	_frameSize(7),
	_widget(NULL),
	_titleBar(NULL),
	_leftFrame(NULL),
	_rightFrame(NULL),
	_bottomFrame(NULL),
	_state(None),
	_cacheImage(NULL)
{
	setWindowFlags(Qt::FramelessWindowHint);
	setAttribute(Qt::WA_TranslucentBackground);
	setMouseTracking(true);

	attachTitleBar(new TitleBarAbstract());
	attachFrame(new FrameAbstract(FrameLeft,this));
	attachFrame(new FrameAbstract(FrameRight,this));
	attachFrame(new FrameAbstract(FrameBottom,this));

	resize(400,300);
}

CustomWindow::~CustomWindow()
{
}

void CustomWindow::setResizable(bool resizable)
{
	_resizable = resizable;
}

void CustomWindow::setHeaderSize(int height)
{
	_headerHeight = height;
	repaint();
}

void CustomWindow::setFrameSize(int size)
{
	_frameSize = size;
	repaint();
}

void CustomWindow::attachWidget(QWidget* widget)
{
	_widget = widget;
	_widget->setParent(this);
	_widget->show();
	_widget->setGeometry(_frameSize,_headerHeight,width()-2*_frameSize,height()-_frameSize-_headerHeight);
}

void CustomWindow::attachTitleBar(TitleBarAbstract* titleBar)
{
	if(_titleBar) delete _titleBar;
	_titleBar = titleBar;
	_titleBar->setParent(this);
	connect(_titleBar,SIGNAL(close()),SLOT(close()));
	connect(_titleBar,SIGNAL(maximize()),SLOT(showMaximized()));
	connect(_titleBar,SIGNAL(minimize()),SLOT(showMinimized()));
	connect(_titleBar,SIGNAL(normalize()),SLOT(showNormal()));

	repaint();
}

void CustomWindow::attachFrame(FrameAbstract* frame)
{
	switch(frame->type()){
		case FrameLeft:
			if(_leftFrame) delete _leftFrame;
			_leftFrame = frame;
			break;
		case FrameRight:
			if(_rightFrame) delete _rightFrame;
			_rightFrame = frame;
			break;
		case FrameBottom:
			if(_bottomFrame) delete _bottomFrame;
			_bottomFrame = frame;
			break;
		default: return;
	}
	frame->setParent(this);
	repaint();
}

void CustomWindow::resizeEvent(QResizeEvent *event)
{
	// resize widgets
	if(_widget){
		_widget->setGeometry(_frameSize,_headerHeight,width()-2*_frameSize,height()-_frameSize-_headerHeight);
	}
	_titleBar->setGeometry(0,0,width(),_headerHeight);
	_leftFrame->setGeometry(0,_headerHeight,_frameSize,height()-_headerHeight-_frameSize);
	_rightFrame->setGeometry(width()-_frameSize,_headerHeight,_frameSize,height()-_headerHeight-_frameSize);
	_bottomFrame->setGeometry(0,height()-_frameSize,width(),_frameSize);

	// draw background
	if(_cacheImage) delete _cacheImage;
	_cacheImage = new QPixmap(size());
	_cacheImage->fill(Qt::transparent);

	QPainter painter(_cacheImage);

	QLinearGradient linearGrad(QPointF(0, 0), QPointF(0, height()));
	linearGrad.setColorAt(0, QColor(0,0,0,0));
	linearGrad.setColorAt(1, QColor(0,0,0,220));

	painter.fillRect(_frameSize,_headerHeight,width()-2*_frameSize,height()-_headerHeight-_frameSize,Qt::transparent);
	painter.setBrush(QBrush(linearGrad));
	painter.drawRect(QRect(_frameSize,_headerHeight,width()-2*_frameSize,height()-_headerHeight-_frameSize));
}

void CustomWindow::paintEvent(QPaintEvent *event)
{
	if(_cacheImage != NULL){
		QPainter painter(this);
		painter.drawPixmap(0, 0, *_cacheImage);
	}
}

void CustomWindow::mousePressEvent  (QMouseEvent *event)
{
	_lastClick = event->pos();
	_mousePos = event->pos();
}

void CustomWindow::mouseReleaseEvent(QMouseEvent *event)
{
	_state = None;
}

void CustomWindow::mouseMoveEvent(QMouseEvent *event)
{
	if(event->buttons() & Qt::LeftButton){
		resizeWindow(event->pos());
		return;
	}

	calculateState(event->pos());
}

QSize CustomWindow::getMinSizes()
{
	int x = 0;//50;
	int y = 0;//_headerHeight + _frameSize + 3;

	x = minimumWidth()>x ? minimumWidth() : x;
	y = minimumHeight()>y ? minimumHeight() : y;

	if(_widget){
		x = _widget->minimumWidth()>x ? _widget->minimumWidth() : x;
		y = _widget->minimumHeight()>y ? _widget->minimumHeight() : y;
	}

	return QSize(x,y) + QSize(x>50 ? x+2*_frameSize : 50, _headerHeight + _frameSize + 3);
}

QSize CustomWindow::getMaxSizes()
{
	int x = 16777215;
	int y = 16777215;

	x = maximumWidth()<x ? maximumWidth() : x;
	y = maximumHeight()<y ? maximumHeight() : y;

	if(_widget){
		x = _widget->maximumWidth()<x ? _widget->maximumWidth() : x;
		y = _widget->maximumHeight()<y ? _widget->maximumHeight() : y;
	}

	return QSize(x,y) + QSize(2*_frameSize, _headerHeight + _frameSize + 3);
}

void CustomWindow::resizeWindow(const QPoint& mousePos)
{
	QPoint diff = mousePos - _lastClick;
	QPoint diff2 = mousePos - _mousePos;

	QPoint wp = window()->pos();
	QSize sz = window()->size();

	QSize minSize = getMinSizes();
	QSize maxSize = getMaxSizes();

	if(_state & Top){
		if(sz.height() > minSize.height() && sz.height() < maxSize.height()) wp.setY(wp.y() + diff.y());
		sz.setHeight(sz.height() - diff.y());
	}
	if(_state & Right){
		sz.setWidth(sz.width() + diff2.x());
	}
	if(_state & Left){
		if(sz.width() > minSize.width() && sz.width() < maxSize.width()) wp.setX(wp.x() + diff.x());
		sz.setWidth(sz.width() - diff.x());
	}
	if(_state & Bottom){
		sz.setHeight(sz.height() + diff2.y());
	}

	if(_state & Move){
		QPoint p = mapToGlobal(mousePos);
		window()->move(p - _lastClick);
	}
	else if(_resizable){

		_mousePos = mousePos;

		if(sz.width() < minSize.width() && sz.width() < maxSize.width()) sz.setWidth(minSize.width());
		if(sz.height() < minSize.height() && sz.height() < maxSize.height()) sz.setHeight(minSize.height());

		window()->setGeometry(wp.x(), wp.y(), sz.width(), sz.height());
		this->repaint();
	}
}


void CustomWindow::calculateState(const QPoint& mousePos)
{
	if(!_resizable){
		if(mousePos.y() < _headerHeight){
			setCursor(Qt::ArrowCursor);
			_state = Move;
		}
		else{
			setCursor(Qt::ArrowCursor);
			_state = None;
		}
		return;
	}
	if(mousePos.x() < _frameSize && mousePos.y() < _frameSize){
		setCursor(Qt::SizeFDiagCursor);
		_state = Left + Top;
	}
	else if(mousePos.x() > width()-_frameSize && mousePos.y() < _frameSize){
		setCursor(Qt::SizeBDiagCursor);
		_state = Right + Top;
	}
	else if(mousePos.y() > height()-_frameSize && mousePos.x() < 2*_frameSize){
		setCursor(Qt::SizeBDiagCursor);
		_state = Left + Bottom;
	}
	else if(mousePos.y() > height()-_frameSize && mousePos.x() > width()-2*_frameSize){
		setCursor(Qt::SizeFDiagCursor);
		_state = Right + Bottom;
	}
	else if(mousePos.x() < _frameSize){
		setCursor(Qt::SizeHorCursor);
		_state = Left;
	}
	else if(mousePos.y() < _frameSize){
		setCursor(Qt::SizeVerCursor);
		_state = Top;
	}
	else if(mousePos.x() > width()-_frameSize){
		setCursor(Qt::SizeHorCursor);
		_state = Right;
	}
	else if(mousePos.y() > height()-_frameSize){
		setCursor(Qt::SizeVerCursor);
		_state = Bottom;
	}
	else if(mousePos.y() < _headerHeight){
		setCursor(Qt::ArrowCursor);
		_state = Move;
	}
	else{
		setCursor(Qt::ArrowCursor);
		_state = None;
	}
}
